// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin 1746365080@qq.com
 * @Date: 2024-11-18 16:44:49
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2025-01-02 17:51:18
 * @FilePath: /SGFEM/DBManager/Repositories/H5/Parameter/ParameterRepository.cpp
 */

#include "ParameterRepository.h"

#include "Utility/Logging/SGLogger.h"

#include "DBManager/Repository/HDF5/Base/HDF5RepositoryMacro.h"

void* NewParameterRepository (SG::DBManager::HDF5Database& dataBase)
{
    return ( void* ) new SG::DBManager::HDF5::ParameterRepository (dataBase);
};
void DelParameterRepository (void* Rep)
{
    delete static_cast<SG::DBManager::HDF5::ParameterRepository*> (Rep);
};
bool H5ParameterRepositoryFunPReg = SG::DBManager::HDF5Database::RegRepoFunP (typeid (IParameterRepository).hash_code (),
                                                                              { NewParameterRepository, DelParameterRepository });

using namespace SG::DBManager::HDF5;

static const std::string TablePath = "/SG/INPUT/PARAMETER/PVT";
ParameterRepository::ParameterRepository (HDF5Database& H5DataBaseSP) : m_H5DataBase (H5DataBaseSP)
{
    if (!m_H5DataBase.GetFile ()->exist (TablePath))
        m_H5DataBase.GetFile ()->createDataSet (TablePath, 3);
}

ParameterRepository::~ParameterRepository () = default;

void ParameterRepository::Initial (SG::Utility::SGParameter entity)
{
    std::string ParameterStr = entity.PrettyPrintJsonString ();  // 待初始化的参数字面量
    auto        dataset      = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const  ishave       = dataset.hasAttribute ("SolverParameter");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("SolverParameter").read (oriStr);
        SGWarn << "For unexpected operations, the parameter is initialized twice\nOriginal parameter:" << oriStr;
        SGWarn << "New parameter:" << ParameterStr;
        dataset.deleteAttribute ("SolverParameter");
    }
    dataset.createAttribute<std::string> ("SolverParameter", ParameterStr);
}

void ParameterRepository::AddExecutiveSystem (SG::Utility::SGParameter entity)
{
    // 取出属性列表的值，如果没有则创建，如果有则修改覆盖
    std::string               ParameterStr;  // 待初始化的参数字面量
    SG::Utility::SGParameter* oldp    = nullptr;
    auto                      dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const                ishave  = dataset.hasAttribute ("ExecutiveSystem");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("ExecutiveSystem").read (oriStr);
        oldp = new SG::Utility::SGParameter (oriStr);

        dataset.deleteAttribute ("ExecutiveSystem");
    }
    else
    {
        oldp = new SG::Utility::SGParameter ("[]");
    }

    oldp->Append (entity);

    ParameterStr = oldp->PrettyPrintJsonString ();

    delete oldp;

    dataset.createAttribute<std::string> ("ExecutiveSystem", ParameterStr);
}

SG::Utility::SGParameter ParameterRepository::GetSolverParameter ()
{
    auto       dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const ishave  = dataset.hasAttribute ("SolverParameter");
    if (!ishave)
    {
        return {};
    }
    std::string str;
    dataset.getAttribute ("SolverParameter").read (str);
    return SG::Utility::SGParameter (str);
}

SG::Utility::SGParameter ParameterRepository::GetExecutiveSystemParameter ()
{
    auto       dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const ishave  = dataset.hasAttribute ("ExecutiveSystem");
    if (!ishave)
    {
        return SG::Utility::SGParameter ("[]");
    }
    std::string str;
    dataset.getAttribute ("ExecutiveSystem").read (str);
    return SG::Utility::SGParameter (str);
}

SG::Utility::SGParameter ParameterRepository::GetCustomParameter () const
{
    auto       dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const ishave  = dataset.hasAttribute ("CustomParameter");
    if (!ishave)
    {
        return SG::Utility::SGParameter ("{}");
    }
    std::string str;
    dataset.getAttribute ("CustomParameter").read (str);
    return SG::Utility::SGParameter (str);
}

void ParameterRepository::SetCustomParameter (std::string key, bool value)
{
    // 取出属性列表的值，如果没有则创建，如果有则修改覆盖
    std::string               ParameterStr;  // 待初始化的参数字面量
    SG::Utility::SGParameter* oldp    = nullptr;
    auto                      dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const                ishave  = dataset.hasAttribute ("CustomParameter");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("CustomParameter").read (oriStr);
        oldp = new SG::Utility::SGParameter (oriStr);

        dataset.deleteAttribute ("CustomParameter");
    }
    else
    {
        oldp = new SG::Utility::SGParameter ("{}");
    }

    oldp->AddBool (key, value);

    ParameterStr = oldp->PrettyPrintJsonString ();

    delete oldp;

    dataset.createAttribute<std::string> ("CustomParameter", ParameterStr);
}

void ParameterRepository::SetCustomParameter (std::string key, int32_t value)
{                                            // 取出属性列表的值，如果没有则创建，如果有则修改覆盖
    std::string               ParameterStr;  // 待初始化的参数字面量
    SG::Utility::SGParameter* oldp    = nullptr;
    auto                      dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const                ishave  = dataset.hasAttribute ("CustomParameter");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("CustomParameter").read (oriStr);
        oldp = new SG::Utility::SGParameter (oriStr);

        dataset.deleteAttribute ("CustomParameter");
    }
    else
    {
        oldp = new SG::Utility::SGParameter ("{}");
    }

    oldp->AddInt (key, value);

    ParameterStr = oldp->PrettyPrintJsonString ();

    delete oldp;

    dataset.createAttribute<std::string> ("CustomParameter", ParameterStr);
}

void ParameterRepository::SetCustomParameter (std::string key, double value)
{                                            // 取出属性列表的值，如果没有则创建，如果有则修改覆盖
    std::string               ParameterStr;  // 待初始化的参数字面量
    SG::Utility::SGParameter* oldp    = nullptr;
    auto                      dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const                ishave  = dataset.hasAttribute ("CustomParameter");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("CustomParameter").read (oriStr);
        oldp = new SG::Utility::SGParameter (oriStr);

        dataset.deleteAttribute ("CustomParameter");
    }
    else
    {
        oldp = new SG::Utility::SGParameter ("{}");
    }

    oldp->AddDouble (key, value);

    ParameterStr = oldp->PrettyPrintJsonString ();

    delete oldp;

    dataset.createAttribute<std::string> ("CustomParameter", ParameterStr);
}

void ParameterRepository::SetCustomParameter (std::string key, std::string value)
{                                            // 取出属性列表的值，如果没有则创建，如果有则修改覆盖
    std::string               ParameterStr;  // 待初始化的参数字面量
    SG::Utility::SGParameter* oldp    = nullptr;
    auto                      dataset = m_H5DataBase.GetFile ()->getDataSet (TablePath);
    bool const                ishave  = dataset.hasAttribute ("CustomParameter");
    if (ishave)
    {
        std::string oriStr;  // j记录先前存在的参数字面量
        dataset.getAttribute ("CustomParameter").read (oriStr);
        oldp = new SG::Utility::SGParameter (oriStr);

        dataset.deleteAttribute ("CustomParameter");
    }
    else
    {
        oldp = new SG::Utility::SGParameter ("{}");
    }

    oldp->AddString (key, value);

    ParameterStr = oldp->PrettyPrintJsonString ();

    delete oldp;

    dataset.createAttribute<std::string> ("CustomParameter", ParameterStr);
}
